/*
    Invtro for Inércia Demoparty 2010

    http://creativecommons.org/licenses/by-nc-sa/2.5/
    
    Victor Martins
    www.pixelnerve.com
    
    
    Our current scene handler.. everything runs here
*/

import java.util.*;
import vitamin.scenesimple.*;   



class CustomScene extends vitamin.fx.Effect
{
    boolean _doUpdate;
    boolean _showCenter;

    VTexture2D _bgTex;
    VTexture2D _centerTex;

    ArrayList _seeds;
    int _stringIndex;

    float _seedInitialVelocity;
    int blackOrWhite;

    Vector3 _center;    
    Vector3 _radarPos;
    float _angle;
    float _angleStep;
    float _lastAngleTarget;
    float _angleTarget;
    float _radius;

    float _maxRadius;    // bounding circle

    Vector3 _constAccel;    // constant acceleratio applied to each seed, when created


    ParticleSystem _pSystem; 

    /**
     *	Initialization method
     */
    public boolean Init( GL gl )
    {
        _gl = gl;

        _doUpdate = true;
        _showCenter = true;

//        _bgTex = new VTexture2D( _gl, dataPath("bg2.jpg") );
//        _centerTex = new VTexture2D( _gl, dataPath("BubbleTexture1.png") );

        //_bubbleTex = new ArrayList();
        //_bubbleTex.add( new VTexture2D( _gl, dataPath("BubbleTexture2.png") ) );
        //_bubbleTex.add( new VTexture2D( _gl, dataPath("plus.png") ) );
        //_bubbleTex.add( new VTexture2D( _gl, dataPath("BubbleTexture1.png") ) );
        //_bubbleTex.add( new VTexture2D( _gl, dataPath("postpone.png") ) );
        //_bubbleTex.add( new VTexture2D( _gl, dataPath("arir27-02.png") ) );
/*
//        _bubbleTex.add( new VTexture2D( _gl, dataPath("BubbleTexture2.png") ) );
        _bubbleTex.add( new VTexture2D( _gl, dataPath("plus.png") ) );
        _bubbleTex.add( new VTexture2D( _gl, dataPath("BubbleTexture1.png") ) );
//        _bubbleTex.add( new VTexture2D( _gl, dataPath("postpone.png") ) );
        _bubbleTex.add( new VTexture2D( _gl, dataPath("arir27-02.png") ) );
//        _bubbleTex.add( new VTexture2D( _gl, dataPath("BubbleTexture2.png") ) );
        _bubbleTex.add( new VTexture2D( _gl, dataPath("plus.png") ) );
        _bubbleTex.add( new VTexture2D( _gl, dataPath("BubbleTexture1.png") ) );
//        _bubbleTex.add( new VTexture2D( _gl, dataPath("postpone.png") ) );
        _bubbleTex.add( new VTexture2D( _gl, dataPath("arir27-02.png") ) );
*/

        println( "create particle system" );
        _pSystem = new ParticleSystem( null ); 
        
        _stringIndex = 0;
        _seeds = new ArrayList();

        _seedInitialVelocity = 15;

        _center = new Vector3( 0, 0, 0 );
        _radarPos = new Vector3();

        _angle = 0;
        _angleStep = .5;
        _angleTarget = 360.0/(float)textStrings.length;//137.5;
        _lastAngleTarget = _angleTarget;

        _radius = 400;

        _maxRadius = 200;

        _gl.glLineWidth( 1 );

        return true;
    }



    void drawArc( float centerX, float centerY, float w, float h, float startAngle, float arcAngle, int steps )
    {
        //
        // Rotate the point of 0 rotation 1/4 turn counter-clockwise.
        startAngle += PI*0.5;


        //        float hr = w / 2f;
        //        float vr = h / 2f;

        //        centerX += hr;
        //        centerY += vr;

        //
        //        float twoPI = (float)(2.0f * Math.PI);
        float angleStep = arcAngle / (float)steps;
        float xx = centerX + sin(startAngle /** twoPI*/) * w;
        float yy = centerY + cos(startAngle /** twoPI*/) * h;

        vgl.beginShape( VGL.LINES );
        vgl.color4( 1, 1, 1, 1 );
        vgl.vertex( xx, yy, 0 );
        for( int i=1; i<=steps; i++ )
        {
            float angle = startAngle + i * angleStep;
            xx = centerX + sin(angle /** twoPI*/) * w;
            yy = centerY + cos(angle /** twoPI*/) * h;
            vgl.vertex( xx, yy, 0 );
        }
        vgl.endShape();
    }



    /**
     *	Render method
     */
    void Render( float time )
    {
/*        vgl.ortho( WIDTH, HEIGHT );

        _gl.glLineWidth( 4 );
        vgl.rect( 400, 400, 0, 4, 4 );
        drawArc( 400, 400, 100, 100, radians(0), radians(-180), 40 );
*/

        RenderScene( time );
    }



    /**
     *	Render method
     */
    public void RenderScene( float time )
    {
        float r = 1.0 / 255.0;
        vgl.setDepthWrite( false );
        vgl.ortho( WIDTH, HEIGHT );
        vgl.beginShape( VGL.QUADS );
        vgl.color4( 217*r, 161*r, 68*r, 1 );
        vgl.vertex( 0, 0, 0 );
        vgl.color4( 245*r, 233*r, 211*r, 1 );
        vgl.vertex( WIDTH, 0, 0 );
        vgl.color4( 245*r, 233*r, 211*r, 1 );
        vgl.vertex( WIDTH, HEIGHT, 0 );
        vgl.color4( 0.3, 0.3, 0.3, 1 );
        vgl.vertex( 0, HEIGHT, 0 );        
/*        vgl.color4( 0.3, 0.3, 0.3, 1 );
        vgl.vertex( 0, 0, 0 );
        vgl.color4( 0.3, 0.3, 0.3, 1 );
        vgl.vertex( WIDTH, 0, 0 );
        vgl.color4( 0.1, 0.1, 0.1, 1 );
        vgl.vertex( WIDTH, HEIGHT, 0 );
        vgl.color4( 0.0, 0.0, 0.0, 1 );
        vgl.vertex( 0, HEIGHT, 0 );*/
        vgl.endShape();
/*        
        vgl.ortho();
        _bgTex.enable();
        vgl.fill( 0.5 );
//        vgl.texCoordScale( 1, 1.05 );
        vgl.rectTopLeft( -1, -1, 0, 2, 5 );
//        vgl.texCoordScale( 1, 1 );
        _bgTex.disable();
*/

        vgl.perspective( 45, aspectRatio, 1, 1000 ); 
        vgl.camera( 0, 0, 400, 0, 0, 0, 0, 1, 0 ); 
        //        vgl.camera( cam.getPosition(), cam.getTarget(), cam.getUp() ); 

        vgl.setDepthWrite( false );
        
        
        // Render particles
        _gl.glLineWidth( 1 );
        _pSystem.render();         
        
        
        
        //
        // Rotate scenario
        //

        vgl.rotateZ( -time*45*0.25 );

        float rads = radians( _angle );
        float newX = cos( rads ) * _radius;
        float newY = sin( rads ) * _radius;
        _radarPos.set( newX, newY, 0 );
        _radarPos.add( _center );


        vgl.enableTexture( false );
        vgl.setDepthMask( false );
//        vgl.setAdditiveBlend();
        vgl.setFlipV( true );

        vgl.fill( 1 );
//        for( int i=_seeds.size()-1; i>=0; i-- )
        for( int i=0; i<_seeds.size(); i++ )
        {
            Seed s = (Seed)_seeds.get( i );

//            ((VTexture2D)_bubbleTex.get(s._texIndex)).enable();
            s.render( time );
//7            ((VTexture2D)_bubbleTex.get(s._texIndex)).disable();

            s.update( time, _maxRadius );
        }



        //
        // Center
        //
        if( _showCenter )
        {
            float centerSize = 30;
//            _centerTex.enable();

            // Draw shadow
            vgl.fill( 0, 0.5 );
//            vgl.rect( _center.x+2, _center.y-2, _center.z, centerSize, centerSize );
            vgl.ellipse( _center.x+2, _center.y-2, _center.z, centerSize, centerSize, 40 );

            // Draw object
            int idx = 1;//(int)random(0, _colors.size() );
            Color4 _color = ((Color4)_colors.get(idx));
            
            vgl.fill( _color.r, _color.g, _color.b, _color.a );    //1 );
            vgl.pushMatrix();
            vgl.translate( _center.x, _center.y, _center.z );
            vgl.rotateZ( time*20 );
            vgl.ellipse( 0, 0, 0, centerSize, centerSize, 40 );
//            vgl.rect( centerSize, centerSize );
//            vgl.rect( _center.x+2, _center.y-2, _center.z, centerSize, centerSize );

            idx = 2;//(int)random(0, _colors.size() );
//            _color = currActiveColor;
            _color = ((Color4)_colors.get(idx));
            vgl.fill( _color.r, _color.g, _color.b, _color.a );    //1 );
            vgl.ellipse( 0, 0, 0, centerSize*0.9, centerSize*0.9, 40 );

            vgl.popMatrix();
            
//            _centerTex.disable();
        }
        
        
        //
        // Draw radar line
        //
        float ss = 0.07;
        vgl.fill( 0.3, 0.5 );
        vgl.beginShape( VGL.LINES );
        vgl.vertex( _center.x, _center.y, _center.z );
        vgl.vertex( _radarPos.x*ss, _radarPos.y*ss, _radarPos.z*ss );
        vgl.endShape();
        vgl.fill( 0.3, 1 );
        vgl.ellipse( 0, 0, 0, 1, 1 );
        vgl.ellipse( _radarPos.x*ss, _radarPos.y*ss, _radarPos.z*ss, 1, 1 );

        
        //vgl.ortho( WIDTH, HEIGHT );
        //textRender.setColor( 1, 1, 1, 0.2 );
        //textRender.print( ""+_seeds.size()+")", WIDTH-100, HEIGHT-30 );
    }


    /**
     *	Update method
     */
    public void Update( float time )
    {
        _pSystem.update( time );             
         
        if( _doUpdate )
        {
            _angleStep = 5.0*0.125;
//            _angleStep = (4.5*0.125) + (time*0.01);
            _angle += _angleStep;

            float angleMargin = _angleStep*1;
            if( _angle > (_angleTarget-angleMargin) && _angle < (_angleTarget+angleMargin) )
            {
                _lastAngleTarget = _angleTarget;
                _angleTarget += 137.5 * 0.15;
//                _angleTarget += 137.5;

                createNewSeed( time );
                _stringIndex++;
            }
        }

        repelBodyParts();
    }


    /**
     *	Release memory
     */
    public void Release()
    {

    }



    /**
     *    Create a new seed
     */
    void createNewSeed( float time )
    {
        Vector3 newPos = new Vector3();
        newPos.x = cos(radians(_lastAngleTarget)) * _radius;
        newPos.y = sin(radians(_lastAngleTarget)) * _radius;
        newPos.add( _center );

        float speed = 1.5;
//        float speed = MathUtils.clamp( _seedInitialVelocity-(time*0.3), 0.01, _seedInitialVelocity );

        float size = (HEIGHT / (float)WIDTH) * 10;

        _constAccel = Vector3.sub( newPos, _center );
        _constAccel.normalize();        
        _constAccel.mul( speed );//random(1, 8) );


        Seed seed = new Seed( _center, _constAccel, size );

//        if( blackOrWhite%2 == 0 )    seed._texIndex = 1;
//        else    seed._texIndex = 0;

        blackOrWhite++;


        _seeds.add( seed );
    }



    /*
    *    Apply repulsive forces to the seed system
     */
    void repelBodyParts()
    {
        for ( int j=0; j<_seeds.size(); j++ )
        {
            for ( int i=j+1; i<_seeds.size(); i++ )
            {
                Seed si = (Seed)_seeds.get( i );
                Seed sj = (Seed)_seeds.get( j );

                if( i != j )
                {
                    // get distance between 2 points
                    Vector3 vec = Vector3.sub( si._pos, sj._pos );
                    float dist = vec.length();

                    // if too far, just don't do anything
//                    if( dist > si._bodyRadius*4 )
//                        continue;

                    //		    float invDist = 1.0 / dist;

                    // If two seeds are too close, move one of them on its correct direction until the system is stable
                    if( dist < (si._bodyRadius+sj._bodyRadius)*0.5 )
                    {
                        sj.applyRepulseForce();

                        // move back one of the touching seeds
                        //                        si._accel = si._repulseForce.copy();
                        //                        si._accel.mul( -0.01 );

                        /*                        si._pos.x += vec.x * invDist * 0.3f;
                         si._pos.y += vec.y * invDist * 0.3f;
                         si._pos.z += vec.z * invDist * 0.3f;*/
                    }
                }
            }
        }
    }

    /*    
     boolean satisfyConstraints( float maxRadius )
     {
     for ( int i=0; i<_seeds.size(); i++ )
     {
     Seed si = (Seed)_seeds.get( i );
     
     // get distance between 2 points
     Vector3 vec = Vector3.sub( si._pos, Vector3.ZERO );
     float dist = vec.length();
     
     if( dist > maxRadius )
     {
     return true;
     }
     }
     
     return false;
     }*/


    // __________________________________________________________
    // Members
    //

    GL _gl;
}


